//
//  ReactiveDevice.hpp
//  Clock Signal
//
//  Created by Thomas Harte on 12/02/2021.
//  Copyright © 2021 Thomas Harte. All rights reserved.
//

#pragma once

#include "Bus.hpp"

#include <atomic>
#include <cstddef>
#include <vector>

namespace Apple::ADB {

class ReactiveDevice: public Bus::Device {
protected:
	ReactiveDevice(Bus &bus, uint8_t adb_device_id);

	void post_response(const std::vector<uint8_t> &&response);
	void post_service_request();
	void receive_bytes(size_t count);

	virtual void perform_command(const Command &command) = 0;
	virtual void did_receive_data(const Command &, const std::vector<uint8_t> &) {}

private:
	void advance_state(double microseconds, bool current_level) override;
	void adb_bus_did_observe_event(Bus::Event event, uint8_t value) override;

	Bus &bus_;
	const size_t device_id_;

	std::vector<uint8_t> response_;
	int bit_offset_ = 0;
	double microseconds_at_bit_ = 0;

	enum class Phase {
		AwaitingAttention,
		AwaitingCommand,
		AwaitingContent,
		ServiceRequestPending,
	} phase_ = Phase::AwaitingAttention;
	std::vector<uint8_t> content_;
	size_t expected_content_size_ = 0;
	Command command_;
	bool stop_has_begin_ = false;

	uint16_t register3_;
	const uint8_t default_adb_device_id_;

	std::atomic<bool> service_desired_ = false;

	void reset();
};

}
